﻿namespace Commands
{
    using System;

    /// <summary>
    /// A class calable of building a <see cref="DelegatingCommand"/>.
    /// </summary>
    public class DelegatingCommandBuilder
    {
        private readonly Action<object> _execute = delegate { };
        private Action _callback;
        private Func<object, bool> _canExectue = delegate { return true; };
        private bool _isAsync;

        /// <summary>
        /// Initializes a new instance of the <see cref="DelegatingCommandBuilder"/> class.
        /// </summary>
        /// <param name="execute">The execute.</param>
        public DelegatingCommandBuilder(Action<object> execute)
        {
            _execute = execute;
        }

        /// <summary>
        /// specifies a method to determine whether the command should execute.
        /// </summary>
        /// <param name="canExecute">The can execute method.</param>
        /// <returns>The builder.</returns>
        public DelegatingCommandBuilder If(Func<object, bool> canExecute)
        {
            _canExectue = canExecute;
            return this;
        }

        /// <summary>
        /// specifies a method to determine whether the command should execute.
        /// </summary>
        /// <param name="canExecute">The can execute method.</param>
        /// <returns>The builder.</returns>
        public DelegatingCommandBuilder If(Func<bool> canExecute)
        {
            _canExectue = (p => canExecute());
            return this;
        }

        /// <summary>
        /// Specifies that the command should execute asnychronously.
        /// </summary>
        /// <returns>The builder.</returns>
        public DelegatingCommandBuilder Async()
        {
            _isAsync = true;
            return this;
        }

        /// <summary>
        /// Specifies that the command should execute asnychronously.
        /// </summary>
        /// <param name="callback">The callback.</param>
        /// <returns>The builder.</returns>
        public DelegatingCommandBuilder Async(Action callback)
        {
            _isAsync = true;
            _callback = callback;
            return this;
        }

        /// <summary>
        /// Builds the command.
        /// </summary>
        /// <returns>The command.</returns>
        public DelegatingCommand Build()
        {
            return new DelegatingCommand(
                _execute,
                _canExectue,
                _isAsync,
                _callback
                );
        }

        /// <summary>
        /// Performs an implicit conversion from <see cref="DelegatingCommandBuilder"/> to <see cref="DelegatingCommand"/>.
        /// </summary>
        /// <param name="builder">The builder.</param>
        /// <returns>The result of the conversion.</returns>
        public static implicit operator DelegatingCommand(DelegatingCommandBuilder builder)
        {
            return builder.Build();
        }
    }
}